package br.net.woodstock.tickettoride.api.manager.common;

import java.util.HashMap;
import java.util.Map;

import javax.crypto.SecretKey;

import br.net.woodstock.rockframework.domain.service.ServiceException;
import br.net.woodstock.rockframework.persistence.orm.QueryMetadata;
import br.net.woodstock.tickettoride.api.core.common.AbstractCommonService;
import br.net.woodstock.tickettoride.api.core.utils.RepositoryHelper;
import br.net.woodstock.tickettoride.api.manager.CertificateService;
import br.net.woodstock.tickettoride.api.manager.SessionService;
import br.net.woodstock.tickettoride.client.utils.CodecUtils;
import br.net.woodstock.tickettoride.client.utils.KeyUtils;
import br.net.woodstock.tickettoride.orm.Certificate;
import br.net.woodstock.tickettoride.orm.Session;

public abstract class AbstractSessionService extends AbstractCommonService implements SessionService {

	private static final long	serialVersionUID			= 1L;

	private static final int	KEY_SIZE					= 64;

	private static final String	JPQL_GET_SESSION_BY_HASH	= "SELECT s FROM Session AS s where s.hash = :hash";

	public abstract CertificateService getCertificateService();

	@Override
	public Session getById(final Integer id) {
		try {
			return this.getSimpleRepository().get(new Session(id));
		} catch (Exception e) {
			throw new ServiceException(e);
		}
	}

	@Override
	public Session getByHash(final String hash) {
		try {
			Map<String, Object> parameters = new HashMap<String, Object>();
			parameters.put("hash", hash);
			QueryMetadata metadata = RepositoryHelper.toQueryMetadata(AbstractSessionService.JPQL_GET_SESSION_BY_HASH, parameters);
			return this.getSimpleQueryableRepository().getSingle(metadata);
		} catch (Exception e) {
			throw new ServiceException(e);
		}
	}

	@Override
	public Integer create(final Integer applicationId) {
		try {
			Certificate certificate = this.getCertificateService().getByApplication(applicationId);

			if (certificate == null) {
				throw new ServiceException("Certificate not found");
			}

			SecretKey secretKey = KeyUtils.newSecretKey();
			byte[] base64Key = CodecUtils.toBase64(secretKey.getEncoded());

			String hash = CodecUtils.getRandomString(AbstractSessionService.KEY_SIZE);

			Session session = new Session();
			session.setCertificate(certificate);
			session.setHash(hash);
			session.setKey(base64Key);
			this.getSimpleRepository().save(session);

			return session.getId();
		} catch (Exception e) {
			throw new ServiceException(e);
		}
	}

}
